package com.gugee.ins.common.model;


import com.gugee.ins.common.dto.InsMediaScoreDto;
import com.gugee.ins.common.model.mysql.blogger.InsBloggerMain;

import java.util.List;

/**
 * 帖子分数算法类
 * @author Huangxin
 */
public class InsMediaScore {
    /*private double avgLikeAll = 4545.1061; //全网平均点赞
    private double avgCommentAll = 67.1834;//全网平均评论
    private double avgAhareAll = 86.5219;//全网平均分享*/

    /**
     * 全网平均点赞
     */
    private double avgLikeAll = 398.5094106922762;
    /**
     * 全网平均评论
     */
    private double avgCommentAll = 18.794965494819685;
    /**
     * 全网平均分享
     */
    private double avgAhareAll = 14.111083658145416;
    
    /**
     * 篇均传播力
     */
    private static final double AVG_SCORE = 100 * 0.05;
    /**
     * 粉丝传播力
     */
    private static final double FANS_SCORE = 100 * 0.25;
    /**
     * 爆款传播力
     */
    private static final double RISE_SCORE = 100 * 0.65;

    /**
     * 播主近期帖子的平均值点赞数
     */
    private double avgLike;
    /**
     * 播主近期帖子的平均值评论数
     */
    private double avgComment;
    /**
     * 播主近期帖子的平均值分享数(分享数这里没拿到用评论数代替)
     */
    private double avgShare;

    /**
     * 播主近期的帖子队列
     */
    List<InsMediaScoreDto> medias;

    /**
     * 播主信息
     */
    private InsBloggerMain bloggerMain;

    /**
     * 播主的得分
     */
    private double bloggerScore;

    /**
     * 构造函数
     * @param bloggerMain
     * @param medias
     */
    public InsMediaScore(InsBloggerMain bloggerMain, List<InsMediaScoreDto> medias){
        this.bloggerMain = bloggerMain;
        this.medias = medias;
        this.init();
    }

    /**
     * 构造函数
     * @param bloggerMain
     * @param medias
     * @param avgLikeAll
     * @param avgCommentAll
     * @param avgShareAll
     */
    public InsMediaScore(InsBloggerMain bloggerMain, List<InsMediaScoreDto> medias,double avgLikeAll,double avgCommentAll,double avgShareAll){
        this.avgLikeAll = avgLikeAll;
        this.avgCommentAll = avgCommentAll;
        this.avgAhareAll = avgShareAll;
        this.bloggerMain = bloggerMain;
        this.medias = medias;
        this.init();
    }

    /**
     *
     * @return
     */
    public InsBloggerMain getBloggerMain(){
        return bloggerMain;
    }

    /**
     * 初始值参数生成
     */
    private void init(){

        // 播主近期帖子的平均值
        avgLike = bloggerMain.getAvgLike();
        avgComment = bloggerMain.getAvgReviews();
        // 分享数这里没拿到用评论数代替
        avgShare = bloggerMain.getAvgReviews();

        // 当帖子没有或者只有一个帖子时
        if (medias != null && medias.size() == 1) {
            avgLike = (10000d + medias.get(0).getLikeCount()) / 2;
            avgComment = (1000d + medias.get(0).getCommentCount()) / 2;
            // 分享数这里没拿到用评论数代替
            avgShare = (100d + medias.get(0).getCommentCount()) / 2;
        }else if(medias == null || medias.isEmpty()){
            bloggerScore = 0.0;
        }

        //计算篇均传播力
        bloggerScore = getRateScore(avgLike, avgLikeAll, avgLike, AVG_SCORE * 0.8, ScoreType.like)
                + getRateScore(avgComment, avgCommentAll, avgComment, AVG_SCORE * 0.1, ScoreType.comment)
                + getRateScore(avgShare, avgAhareAll, avgShare, AVG_SCORE * 0.1, ScoreType.share);
    }

    /**
     * 计算帖子的分数
     * @param media
     * @return
     */
    public double getMediaScore(InsMediaScoreDto media) {
        //计算篇均传播力
        var score1 = bloggerScore;

        if(score1 == 0){
            return 0.0;
        }

        //计算粉丝传播力
        var score2 = getFansScore(media.getLikeCount(), bloggerMain.getFollowerCount(), FANS_SCORE);

        //计算音乐传播力
        var score3 = 4.5;

        //计算爆款传播力
        var score4_1 = getRateScore(media.getLikeCount() - avgLike, avgLike, media.getLikeCount(), RISE_SCORE * 0.8, ScoreType.like);
        var score4_2 = getRateScore(media.getCommentCount() - avgComment, avgComment, media.getCommentCount(), RISE_SCORE * 0.1, ScoreType.comment);
        var score4_3 = getRateScore(media.getCommentCount() - avgShare, avgShare, media.getCommentCount(), RISE_SCORE * 0.1, ScoreType.share);
        var score4 = score4_1 + score4_2 + score4_3;

        double scoreTotal = score1 + score2 + score3 + score4;
        double rawScore;
        if(scoreTotal < 0){
            rawScore = 0;
        } else {
            rawScore = scoreTotal > 100 ? 100 : scoreTotal;
        }

        //确保视频点赞大于500万热度值不低于80，视频点赞大于1000万热度值不低于90
        var bottomScore = 0.0;
        if (media.getLikeCount() >= 500 * 10000 && media.getLikeCount() <= 1000 * 10000) {
            bottomScore = 80 + ((media.getLikeCount() - 500 * 10000) * (10.0 / 500 / 10000));
        }
        if (media.getLikeCount() > 1000 * 10000) {
            bottomScore = 90 + Math.log10(media.getLikeCount() - 1000 * 10000d) / 4;
        }
        var finScore = Math.max(rawScore, bottomScore);

        if (Double.isNaN(finScore)) {
            finScore = 0;
        }

        if (finScore == 0) {
            finScore = 0.1; //最低保底分
        }

        return finScore;
    }

    /**
     *
     * @param d1
     * @param d2
     * @param d3
     * @param score
     * @param type
     * @return
     */
    private double getRateScore(double d1, double d2, double d3, double score, ScoreType type) {
        if (d1 < 0) {
            return 0;
        }

        var difficult = getDifficult(d1, type);
        var difficult2 = getDifficult(d3, type);
        var rate = d1 / d2 * difficult;
        if (type == ScoreType.like) {
            if (rate > 1) {
                var scale = Math.log(rate) / Math.log(50 * difficult);
                scale = scale > 1 ? 1 : scale;
                return score * 0.6 * scale + score * 0.4 * difficult2;
            } else {
                return score * 0.1 * rate + score * 0.4 * difficult2;
            }
        }
        if (type == ScoreType.comment) {
            if (rate > 1) {
                var scale = Math.log(rate) / Math.log(5 * difficult);
                scale = scale > 1 ? 1 : scale;
                return score * 0.6 * scale + score * 0.4 * difficult2;
            } else {
                return score * 0.1 * rate + score * 0.4 * difficult2;
            }
        }
        if (type == ScoreType.share) {
            if (rate > 1) {
                var scale = Math.log(rate) / Math.log(5 * difficult);
                scale = scale > 1 ? 1 : scale;
                return score * 0.6 * scale + score * 0.4 * difficult2;
            } else {
                return score * 0.1 * rate + score * 0.4 * difficult2;
            }
        }
        return score;
    }

    /**
     *
     * @param likes
     * @param fans
     * @param score
     * @return
     */
    private double getFansScore(double likes, double fans, double score) {
        if (likes == 0) {
            return 0;
        }
        //Math.Log(d1 / d2) / Math.Log(100) > 1 ? score : Math.Log(d1 / d2) / Math.Log(100) * score;
        var difficult = getDifficult(likes + 1, ScoreType.like);
        var difficult2 = Math.log(fans + 1) / Math.log(300000) > 1 ? 1 : Math.log(fans + 1) / Math.log(300000);

        var scaleLikes = fans * 1.0 / 100;
        var rate = (likes + 1) / scaleLikes * difficult;

        var scale = Math.log(rate) / Math.log(50 * difficult);
        scale = scale > 1 ? 1 : scale;
        return score * 0.6 * scale + score * 0.4 * difficult2;

    }

    /**
     *
     * @param d
     * @param type
     * @return
     */
    private double getDifficult(double d, ScoreType type) {
        if (type == ScoreType.like) {
            return Math.log(d + 1) / Math.log(500000) > 1 ? 1 : Math.log(d + 1) / Math.log(500000);
        }
        if (type == ScoreType.comment) {
            return Math.log(d + 1) / Math.log(10000) > 1 ? 1 : Math.log(d + 1) / Math.log(10000);
        }
        if (type == ScoreType.share) {
            return Math.log(d + 1) / Math.log(10000) > 1 ? 1 : Math.log(d + 1) / Math.log(10000);
        }
        return 1d;
    }

    /**
     *
     */
    private enum ScoreType {
        like,
        comment,
        share
    }
}
